"""
百度AI开放平台API测试

测试BaiduAI类及相关功能类的功能，使用mock模拟请求，避免实际调用API。
"""

import unittest
from unittest.mock import patch, MagicMock
import json
from cn_api_adapters import BaiduAI, BaiduOCR, BaiduSpeech, BaiduNLP
from cn_api_adapters.common.exceptions import APIError, AuthenticationError
from cn_api_adapters.common.baiduai.exceptions import BaiduAIError


class TestBaiduAI(unittest.TestCase):
    """测试BaiduAI基类的功能"""
    
    def setUp(self):
        """设置测试环境"""
        self.api_key = "test_api_key"
        self.secret_key = "test_secret_key"
        self.ai = BaiduAI(
            api_key=self.api_key,
            secret_key=self.secret_key,
            debug=False
        )
    
    @patch('cn_api_adapters.common.baiduai.baidu_ai.BaiduAI._request')
    def test_get_access_token(self, mock_request):
        """测试获取AccessToken"""
        # 模拟成功响应
        mock_response = {
            "access_token": "mock_access_token",
            "expires_in": 2592000
        }
        mock_request.return_value = mock_response
        
        # 获取access_token
        result = self.ai.get_access_token()
        
        # 验证结果
        self.assertEqual(result, "mock_access_token")
        self.assertEqual(self.ai._access_token, "mock_access_token")
        mock_request.assert_called_once_with(
            "POST",
            "https://aip.baidubce.com/oauth/2.0/token",
            params={
                "grant_type": "client_credentials",
                "client_id": self.api_key,
                "client_secret": self.secret_key
            }
        )
    
    def test_set_access_token(self):
        """测试设置AccessToken"""
        # 设置token
        self.ai.set_access_token("test_access_token")
        
        # 验证设置结果
        self.assertEqual(self.ai._access_token, "test_access_token")
    
    @patch('cn_api_adapters.common.baiduai.baidu_ai.BaiduAI._request')
    def test_error_handling(self, mock_request):
        """测试错误处理"""
        # 模拟错误响应
        mock_request.return_value = {
            "error": "invalid_client",
            "error_description": "client_id or client_secret is invalid"
        }
        
        # 验证抛出BaiduAIError异常
        with self.assertRaises(BaiduAIError):
            self.ai.get_access_token()


class TestBaiduOCR(unittest.TestCase):
    """测试BaiduOCR类的功能"""
    
    def setUp(self):
        """设置测试环境"""
        self.api_key = "test_api_key"
        self.secret_key = "test_secret_key"
        self.ocr = BaiduOCR(
            api_key=self.api_key,
            secret_key=self.secret_key,
            debug=False
        )
    
    @patch('cn_api_adapters.common.baiduai.baidu_ai.BaiduOCR._request')
    def test_basic_general_ocr(self, mock_request):
        """测试通用文字识别"""
        # 模拟access_token和成功响应
        mock_request.side_effect = [
            {"access_token": "mock_access_token", "expires_in": 2592000},
            {
                "words_result": [
                    {"words": "测试文本1"},
                    {"words": "测试文本2"}
                ],
                "words_result_num": 2,
                "log_id": 1234567890
            }
        ]
        
        # 模拟图像数据
        image_data = b"mock_image_data"
        
        # 调用通用文字识别
        result = self.ocr.basic_general(image_data)
        
        # 验证结果
        self.assertEqual(len(result["words_result"]), 2)
        self.assertEqual(result["words_result"][0]["words"], "测试文本1")
        mock_request.assert_called_with(
            "POST",
            "https://aip.baidubce.com/rest/2.0/ocr/v1/general_basic",
            params={"access_token": "mock_access_token"},
            data={"image": b"mock_image_data"}
        )
    
    @patch('cn_api_adapters.common.baiduai.baidu_ai.BaiduOCR._request')
    def test_accurate_general_ocr(self, mock_request):
        """测试通用文字识别（高精度版）"""
        # 模拟access_token和成功响应
        mock_request.side_effect = [
            {"access_token": "mock_access_token", "expires_in": 2592000},
            {
                "words_result": [
                    {"words": "高精度测试文本"}
                ],
                "words_result_num": 1,
                "log_id": 1234567890
            }
        ]
        
        # 模拟图像数据
        image_data = b"mock_image_data"
        
        # 调用高精度文字识别
        result = self.ocr.accurate_general(image_data, detect_direction=True)
        
        # 验证结果
        self.assertEqual(result["words_result"][0]["words"], "高精度测试文本")
        mock_request.assert_called_with(
            "POST",
            "https://aip.baidubce.com/rest/2.0/ocr/v1/accurate_basic",
            params={"access_token": "mock_access_token"},
            data={"image": b"mock_image_data", "detect_direction": True}
        )
    
    @patch('cn_api_adapters.common.baiduai.baidu_ai.BaiduOCR._request')
    def test_id_card_ocr(self, mock_request):
        """测试身份证识别"""
        # 模拟access_token和成功响应
        mock_request.side_effect = [
            {"access_token": "mock_access_token", "expires_in": 2592000},
            {
                "words_result": {
                    "姓名": {"words": "张三"},
                    "公民身份号码": {"words": "110101199001011234"}
                },
                "log_id": 1234567890
            }
        ]
        
        # 模拟身份证图像数据
        image_data = b"mock_id_card_image"
        
        # 调用身份证识别
        result = self.ocr.id_card(image_data, id_card_side="front")
        
        # 验证结果
        self.assertEqual(result["words_result"]["姓名"]["words"], "张三")
        self.assertEqual(result["words_result"]["公民身份号码"]["words"], "110101199001011234")
        mock_request.assert_called_with(
            "POST",
            "https://aip.baidubce.com/rest/2.0/ocr/v1/idcard",
            params={"access_token": "mock_access_token"},
            data={"image": b"mock_id_card_image", "id_card_side": "front"}
        )
    
    @patch('cn_api_adapters.common.baiduai.baidu_ai.BaiduOCR._request')
    def test_business_license_ocr(self, mock_request):
        """测试营业执照识别"""
        # 模拟access_token和成功响应
        mock_request.side_effect = [
            {"access_token": "mock_access_token", "expires_in": 2592000},
            {
                "words_result": {
                    "单位名称": {"words": "测试公司"},
                    "统一社会信用代码": {"words": "91110101MA12345678"}
                },
                "log_id": 1234567890
            }
        ]
        
        # 模拟营业执照图像数据
        image_data = b"mock_license_image"
        
        # 调用营业执照识别
        result = self.ocr.business_license(image_data)
        
        # 验证结果
        self.assertEqual(result["words_result"]["单位名称"]["words"], "测试公司")
        self.assertEqual(result["words_result"]["统一社会信用代码"]["words"], "91110101MA12345678")


class TestBaiduSpeech(unittest.TestCase):
    """测试BaiduSpeech类的功能"""
    
    def setUp(self):
        """设置测试环境"""
        self.api_key = "test_api_key"
        self.secret_key = "test_secret_key"
        self.speech = BaiduSpeech(
            api_key=self.api_key,
            secret_key=self.secret_key,
            debug=False
        )
    
    @patch('cn_api_adapters.common.baiduai.baidu_ai.BaiduSpeech._request')
    def test_speech_recognition(self, mock_request):
        """测试语音识别"""
        # 模拟access_token和成功响应
        mock_request.side_effect = [
            {"access_token": "mock_access_token", "expires_in": 2592000},
            {
                "result": ["测试语音识别结果"],
                "err_no": 0,
                "err_msg": "success.",
                "corpus_no": "1234567890",
                "sn": "1234567890"
            }
        ]
        
        # 模拟音频数据
        audio_data = b"mock_audio_data"
        
        # 调用语音识别
        result = self.speech.speech_recognition(audio_data, 16000, 1)
        
        # 验证结果
        self.assertEqual(result["result"][0], "测试语音识别结果")
        mock_request.assert_called_with(
            "POST",
            "https://vop.baidu.com/server_api",
            params={"access_token": "mock_access_token"},
            json={
                "format": "pcm",
                "rate": 16000,
                "channel": 1,
                "token": "mock_access_token",
                "cuid": "baidu-api-adapter",
                "len": len(audio_data),
                "speech": "mock_audio_data"
            }
        )
    
    @patch('cn_api_adapters.common.baiduai.baidu_ai.BaiduSpeech._request')
    def test_text_to_speech(self, mock_request):
        """测试语音合成"""
        # 模拟access_token和成功响应（二进制音频数据）
        mock_request.side_effect = [
            {"access_token": "mock_access_token", "expires_in": 2592000},
            b"mock_audio_binary_data"
        ]
        
        # 调用语音合成
        result = self.speech.text_to_speech("测试文本转语音", per=0, spd=5, pit=5, vol=5)
        
        # 验证结果
        self.assertEqual(result, b"mock_audio_binary_data")
        mock_request.assert_called_with(
            "POST",
            "https://tsn.baidu.com/text2audio",
            params={
                "access_token": "mock_access_token",
                "tex": "测试文本转语音",
                "lan": "zh",
                "cuid": "baidu-api-adapter",
                "ctp": 1,
                "per": 0,
                "spd": 5,
                "pit": 5,
                "vol": 5
            },
            response_content_type="binary"
        )


class TestBaiduNLP(unittest.TestCase):
    """测试BaiduNLP类的功能"""
    
    def setUp(self):
        """设置测试环境"""
        self.api_key = "test_api_key"
        self.secret_key = "test_secret_key"
        self.nlp = BaiduNLP(
            api_key=self.api_key,
            secret_key=self.secret_key,
            debug=False
        )
    
    @patch('cn_api_adapters.common.baiduai.baidu_ai.BaiduNLP._request')
    def test_word_seg(self, mock_request):
        """测试中文分词"""
        # 模拟access_token和成功响应
        mock_request.side_effect = [
            {"access_token": "mock_access_token", "expires_in": 2592000},
            {
                "words": ["百度", "是", "一家", "高科技", "公司"],
                "items": [
                    {"word": "百度", "location": 0, "basic_words": ["百度"]},
                    {"word": "是", "location": 2, "basic_words": ["是"]}
                ],
                "log_id": 1234567890
            }
        ]
        
        # 调用中文分词
        result = self.nlp.word_seg("百度是一家高科技公司")
        
        # 验证结果
        self.assertEqual(result["words"], ["百度", "是", "一家", "高科技", "公司"])
        mock_request.assert_called_with(
            "POST",
            "https://aip.baidubce.com/rpc/2.0/nlp/v1/wordseg",
            params={"access_token": "mock_access_token"},
            json={"text": "百度是一家高科技公司"}
        )
    
    @patch('cn_api_adapters.common.baiduai.baidu_ai.BaiduNLP._request')
    def test_sentiment_analysis(self, mock_request):
        """测试情感分析"""
        # 模拟access_token和成功响应
        mock_request.side_effect = [
            {"access_token": "mock_access_token", "expires_in": 2592000},
            {
                "text": "今天天气真好",
                "items": [{
                    "sentiment": 2,  # 2表示积极
                    "confidence": 0.95,
                    "positive_prob": 0.96,
                    "negative_prob": 0.04
                }],
                "log_id": 1234567890
            }
        ]
        
        # 调用情感分析
        result = self.nlp.sentiment_analysis("今天天气真好")
        
        # 验证结果
        self.assertEqual(result["items"][0]["sentiment"], 2)
        self.assertEqual(result["items"][0]["confidence"], 0.95)
        mock_request.assert_called_with(
            "POST",
            "https://aip.baidubce.com/rpc/2.0/nlp/v1/sentiment",
            params={"access_token": "mock_access_token"},
            json={"text": "今天天气真好"}
        )
    
    @patch('cn_api_adapters.common.baiduai.baidu_ai.BaiduNLP._request')
    def test_keyword_extraction(self, mock_request):
        """测试关键词抽取"""
        # 模拟access_token和成功响应
        mock_request.side_effect = [
            {"access_token": "mock_access_token", "expires_in": 2592000},
            {
                "items": [
                    {"tag": "百度", "score": 0.9},
                    {"tag": "AI", "score": 0.8}
                ],
                "log_id": 1234567890
            }
        ]
        
        # 调用关键词抽取
        result = self.nlp.keyword_extraction("百度AI技术领先全球")
        
        # 验证结果
        self.assertEqual(len(result["items"]), 2)
        self.assertEqual(result["items"][0]["tag"], "百度")
        mock_request.assert_called_with(
            "POST",
            "https://aip.baidubce.com/rpc/2.0/nlp/v1/keyword",
            params={"access_token": "mock_access_token"},
            json={"text": "百度AI技术领先全球", "title": ""}
        )
    
    @patch('cn_api_adapters.common.baiduai.baidu_ai.BaiduNLP._request')
    def test_text_summarization(self, mock_request):
        """测试文本摘要"""
        # 模拟access_token和成功响应
        mock_request.side_effect = [
            {"access_token": "mock_access_token", "expires_in": 2592000},
            {
                "summary": "这是一段摘要内容。",
                "log_id": 1234567890
            }
        ]
        
        # 调用文本摘要
        result = self.nlp.text_summarization("这是一段需要生成摘要的长文本内容...", max_summary_len=20)
        
        # 验证结果
        self.assertEqual(result["summary"], "这是一段摘要内容。")
        mock_request.assert_called_with(
            "POST",
            "https://aip.baidubce.com/rpc/2.0/nlp/v1/news_summary",
            params={"access_token": "mock_access_token"},
            json={"text": "这是一段需要生成摘要的长文本内容...", "max_summary_len": 20}
        )


if __name__ == '__main__':
    unittest.main()